//    Copyright (C) Kherty.  All rights reserved.
using System;
using System.Collections.Generic;
using OpenLS.Core.Formatting;

namespace OpenLS.Core
{
    
    public class DateTimeFormat : Format
    {
        
        public DateTimeFormat(string code)
            : base(code)
        {
        }
        string _actualCode;
        string _stringCode;
        private bool _usesTotalHours;
        public override object GetFormattedValue(object o, IFormatValueConverter converter)
        {
            if (o == null)
                return "";
            if (o is bool)
                return BooleanToString((bool)o);
            if (o is DateTime)
                return GetFormattedValue((DateTime)o);
            if (o is string)
                return o;
            if (converter != null)
            {
                return GetFormattedValue(converter.ChangeType<DateTime>(o), converter);
            }
            throw new NotSupportedException();
        }
        public object GetFormattedValue(DateTime dt)
        {
            if (_usesTotalHours)
                return string.Format(_actualCode, dt, (int) Math.Floor((dt - new DateTime(1899, 12, 31)).TotalHours));
            return string.Format(_actualCode, dt);
        }

        public override bool CanFormat(object o)
        {
            if (o == null)
                return true;
            if (o is bool)
                return true;
            if (o is DateTime)
                return true;
            return false;
        }

        internal sealed override void Analyze(List<FormatToken> list)
        {
            bool hasHour = false;
            bool usesAmpm = false;
            foreach (FormatToken token in list)
            {
                if (token is DateTimeToken)
                {
                    var dtt = (DateTimeToken)token;
                    if (dtt.DatePart != null && !dtt.DatePart.Value)
                        hasHour = true;
                    if (dtt.DatePart == null )
                        dtt._forceMinute = hasHour;
                    if (_usesTotalHours)
                        dtt._forceMinute = true;


                }
                if (token is TotalHoursToken)
                {
                    _usesTotalHours = true;
                }
                if (token is AmPmToken)
                {
                    usesAmpm = true;
                }
            }
            bool usesString = false;
            _actualCode = "{";
            int? currentArgument = null;
            foreach (FormatToken t in list)
            {
                if (t is CurrencyToken)
                    continue;
                if (t is ExplicitStringToken && ((ExplicitStringToken)t).Code == @"@")
                    continue;

                if (t is ClauseFormatToken)
                {
                    if (usesString)
                        _stringCode += t.Code;
                    else
                    {
                        int requestArgument;
                        if (t is TotalHoursToken)
                            requestArgument = 1;
                        else
                        {
                            requestArgument = 0;
                        }
                        if (currentArgument == null)
                        {
                            currentArgument = requestArgument;
                            _actualCode += requestArgument+":";
                        }
                        else if (currentArgument.GetValueOrDefault()!= requestArgument)
                        {
                            _actualCode += "}{" + requestArgument + ":";
                            currentArgument = requestArgument;

                        }
                        string code = t.Code;
                        if (usesAmpm)
                            code = code.Replace('H', 'h');
                        _actualCode += code;
                    }
                    continue;
                }
                if (t is ClauseSeparatorToken)
                {
                    usesString = true;
                    continue;
                }
                if (t is FormatParser.UnhandledToken)
                {
                    continue;
                }
                Warn();
            }
            _actualCode += "}";
        }

        public override FormatCategory Category
        {
            get { return FormatCategory.Date; //\\ 
            }
        }
    }
}
